package com.javasm.boot.oauth2.config;

import com.javasm.boot.oauth2.entity.Response;
import com.javasm.boot.oauth2.utils.IgoreUrlByRedis;
import com.javasm.boot.oauth2.utils.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

/**
 * Author：MoDebing
 * Version：1.0
 * Date：2022-12-13-12:04
 * Description:
 */
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private IgoreUrlByRedis igoreUrlByRedis;

    @Autowired
    private WebUtils webUtils;

    @Bean
    public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter(){
        return new WebSecurityConfigurerAdapter() {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                String[] ignoreUrls = igoreUrlByRedis.getIgnoreUrls().toArray(new String[0]);
                String[] blankUrls = igoreUrlByRedis.getUrls().toArray(new String[0]);
                http.cors().disable();
                http.csrf().disable();
                if (!CollectionUtils.isEmpty(Arrays.asList(ignoreUrls))){
                    http.authorizeRequests()
                            .antMatchers(ignoreUrls).permitAll();
                }
                if (!CollectionUtils.isEmpty(Arrays.asList(blankUrls))){
                    http.authorizeRequests()
                            .antMatchers(blankUrls).authenticated();
                }
                // 处理为认证和未授权
                http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint());
            }
        };

    }


    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return webSecurityConfigurerAdapter().authenticationManagerBean();
    }


    // 处理未认证
    @Bean
    public AccessDeniedHandler accessDeniedHandler(){
        return  new AccessDeniedHandler() {
            @Override
            public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
                Response resp = new Response().code(HttpStatus.UNAUTHORIZED).msg("未授权,details:"+e.getMessage());
                webUtils.renderString(resp);
            }
        };
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint(){
        return new AuthenticationEntryPoint() {
            @Override
            public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                Response resp = new Response().code(HttpStatus.FORBIDDEN).msg("未认证,details:"+e.getMessage());
                webUtils.renderString(resp);
            }
        };
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
